package jnpf.engine.custom.type;

import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jnpf.base.UserInfo;
import jnpf.base.util.SentMessageUtil;
import jnpf.engine.custom.constants.BasicActivitiConstants;
import jnpf.engine.custom.helper.UserTaskNodeHelper;
import jnpf.engine.entity.FlowTaskOperatorEntity;
import jnpf.engine.entity.FlowTaskOperatorRecordEntity;
import jnpf.engine.enums.FlowRecordEnum;
import jnpf.engine.enums.FlowTaskStatusEnum;
import jnpf.engine.model.FlowTaskDTO;
import jnpf.engine.model.FlowTaskNodeDTO;
import jnpf.engine.model.FlowTaskOperatorRecordDTO;
import jnpf.engine.model.flowbefore.FlowTemplateAllModel;
import jnpf.engine.model.flowengine.FlowModel;
import jnpf.engine.model.flowengine.shuntjson.childnode.FuncConfig;
import jnpf.engine.model.flowengine.shuntjson.childnode.MsgConfig;
import jnpf.engine.model.flowengine.shuntjson.childnode.Properties;
import jnpf.engine.model.flowmessage.FlowMsgModel;
import jnpf.engine.service.FlowTaskOperatorRecordService;
import jnpf.engine.service.FlowTaskOperatorService;
import jnpf.engine.util.FlowMsgUtil;
import jnpf.engine.util.FlowTaskUtil;
import jnpf.engine.util.SpringContextHolder;
import jnpf.message.model.SentMessageForm;
import jnpf.util.*;
import lombok.extern.slf4j.Slf4j;
//import org.flowable.common.engine.api.delegate.event.FlowableEvent;
//import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.apache.logging.log4j.util.Strings;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.delegate.event.impl.FlowableEntityEventImpl;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.springframework.stereotype.Component;

import java.util.*;

import static jnpf.engine.custom.constants.GlobalProcessVariableConstants.*;
import static jnpf.engine.util.BpmnModelUtils.*;

/**
 * @author LoveMyOrange
 * @create 2022-01-18 17:23
 */
@Slf4j
@Component
public class ProcessCompletedListener  implements FlowableEventListener {
    @Override
    public void onEvent(FlowableEvent event) {
        if(event instanceof FlowableEntityEventImpl) {
            FlowableEntityEventImpl activitiEntityEvent = (FlowableEntityEventImpl) event;
            UserTaskNodeHelper userTaskNodeHelper = SpringContextHolder.getBean(UserTaskNodeHelper.class);
            SentMessageUtil sentMessageUtil = SpringContextHolder.getBean(SentMessageUtil.class);
            ExecutionEntity entity = (ExecutionEntity) activitiEntityEvent.getEntity();
            String processInstanceId = activitiEntityEvent.getProcessInstanceId();
            RuntimeService runtimeService = SpringContextHolder.getBean(RuntimeService.class);
            FlowMsgUtil flowMsgUtil = SpringContextHolder.getBean(FlowMsgUtil.class);
            FlowTaskUtil flowTaskUtil = SpringContextHolder.getBean(FlowTaskUtil.class);
            UserProvider userProvider = SpringContextHolder.getBean(UserProvider.class);
            FlowTaskOperatorService flowTaskOperatorService = SpringContextHolder.getBean(FlowTaskOperatorService.class);
            FlowTaskOperatorRecordService flowTaskOperatorRecordService = SpringContextHolder.getBean(FlowTaskOperatorRecordService.class);
            FlowModel flowModel = new FlowModel();
            flowModel.setTaskId(processInstanceId);


            runtimeService.setVariable(entity.getProcessInstanceId(), PROCESS_STATUS, FlowTaskStatusEnum.Adopt.getCode());
            Map<String, Object> processVariables = entity.getVariables();
            UserInfo userInfo = userProvider.get();
            FlowTemplateAllModel templateAllModel = flowTaskUtil.templateJson(MapUtil.getStr(processVariables, FLOW_TEMPLATE_JSON_ID));
            FlowTaskOperatorRecordEntity operatorRecord = new FlowTaskOperatorRecordEntity();
            operatorRecord.setNodeCode(BasicActivitiConstants.endEventId);
            operatorRecord.setNodeName("流程结束");
            operatorRecord.setHandleId(userInfo.getUserId());
            operatorRecord.setReceiveTime(new Date());
            operatorRecord.setOperatorId(userInfo.getUserId());
//        operatorRecord.setTaskOperatorId(operator.getId());
//        operatorRecord.setTaskNodeId(historicTaskInstance.getId());
            operatorRecord.setTaskId(processInstanceId);
            operatorRecord.setId(RandomUtil.uuId());
            operatorRecord.setHandleStatus(FlowRecordEnum.end.getCode());
            operatorRecord.setHandleTime(new Date());
            flowTaskOperatorRecordService.save(operatorRecord);

            //1.2调用事件
            Process bpmnModelMainProcess = getBpmnModelMainProcess(entity.getProcessDefinitionId());
            UserTask firstNode = getFirstNode(bpmnModelMainProcess);
            Properties properties = getFirstNodeProperty(entity.getProcessDefinitionId());
            Map<String, Object> map = flowTaskUtil.infoData(properties.getFormId(), entity.getProcessInstanceBusinessKey());
            flowModel.setFormData(map);
            //事件调用
            FlowTaskOperatorRecordDTO flowTaskOperatorRecordDTO = new FlowTaskOperatorRecordDTO();
            flowTaskOperatorRecordDTO.setAssignee(MapUtil.getStr(processVariables,APPLY_USER_ID));
            flowTaskOperatorRecordDTO.setProcessInstanceId(processInstanceId);
            flowTaskOperatorRecordDTO.setTaskId(processInstanceId);
            flowMsgUtil.event(2, properties, flowTaskOperatorRecordDTO, flowModel,bpmnModelMainProcess, Strings.EMPTY);

            LambdaQueryWrapper<FlowTaskOperatorEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(FlowTaskOperatorEntity::getTaskId, entity.getProcessInstanceId());
            lambdaQueryWrapper.eq(FlowTaskOperatorEntity::getNodeCode, firstNode.getId());
            FlowTaskOperatorEntity operator = flowTaskOperatorService.list(lambdaQueryWrapper).get(0);
            //1.3调用通知
            Properties firstNodeProperty = getFirstNodeProperty(entity.getProcessDefinitionId());
            MsgConfig endMsgConfig = properties.getEndMsgConfig();
            Integer msgConfigOnn = endMsgConfig.getOn();

            Boolean messageFlag=false;
            if(msgConfigOnn!=0){
                if(msgConfigOnn==2){
                    if(firstNodeProperty.getEndMsgConfig().getOn()!=0){
                        messageFlag=true;
                    }
                }
                else{
                    messageFlag=true;
                }
            }
            if(messageFlag){
                FlowMsgModel flowMsgModel = new FlowMsgModel();
                flowMsgModel.setStartNodeProperties(firstNodeProperty);
                flowMsgModel.setCurrentNodeProperties(properties);
                flowMsgModel.setWait(Boolean.FALSE);
                flowMsgModel.setEnd(Boolean.TRUE);
//                    flowMsgModel.setNodeList(taskNodeList);
                List<FlowTaskOperatorEntity> operatorEntityList = new ArrayList<>();
                operatorEntityList.add(operator);
                flowMsgModel.setOperatorList(operatorEntityList);
                flowMsgModel.setData(flowModel.getFormData());
//                    flowMsgModel.setFlowModel(flowModel);
                FlowTaskDTO flowTaskDTO = new FlowTaskDTO();

                flowTaskDTO.setCreatorUserId(MapUtil.getStr(processVariables, APPLY_USER_ID));
                flowTaskDTO.setStatus(MapUtil.getInt(processVariables, PROCESS_STATUS));
                flowTaskDTO.setFullName(MapUtil.getStr(processVariables, BUSINESS_TITLE));
                flowMsgModel.setTaskEntity(flowTaskDTO);

                FlowTaskNodeDTO flowTaskNodeDTO = new FlowTaskNodeDTO();
                flowTaskNodeDTO.setTaskId(entity.getProcessInstanceId());
                flowTaskNodeDTO.setTaskNodeId(operator.getTaskNodeId());
                flowMsgModel.setTaskNodeEntity(flowTaskNodeDTO);
                flowModel.setUserInfo(UserProvider.getUser());
                flowMsgModel.setFlowModel(flowModel);
                flowMsgModel.setFlowTemplateAllModel(templateAllModel);
                flowMsgModel.setTaskId(entity.getProcessInstanceId());
                flowMsgModel.setTaskNodeId(operator.getTaskNodeId());
                flowMsgUtil.message(flowMsgModel);
            }



        }
    }

    @Override
    public boolean isFailOnException() {
        return true;
    }

    @Override
    public boolean isFireOnTransactionLifecycleEvent() {
        return false;
    }

    @Override
    public String getOnTransaction() {
        return null;
    }



    /**
     * 发送消息封装
     *
     * @param title       名称
     * @param type        类型
     * @param messageType 发送消息类型
     * @param userList    发送用户
     * @return
     */
    private SentMessageForm message(String title, int type, List<String> messageType, String processInstanceId, List<String> userList, String fullName) {
        SentMessageForm sentMessageForm = new SentMessageForm();
//        sentMessageForm.setSendType(messageType);
        Map<String, Object> message = new HashMap<>(16);
        message.put("type", type);
        message.put("id", processInstanceId);
        sentMessageForm.setContent(JsonUtilEx.getObjectToString(message));
        sentMessageForm.setTitle(fullName + title);
        sentMessageForm.setToUserIds(userList);
        Map<String, String> smsContent = new HashMap<>(16);
        this.message(fullName, title, smsContent);
//        sentMessageForm.setSmsContent(smsContent);
        return sentMessageForm;
    }

    /**
     * 短信模板
     *
     * @param title  标题
     * @param status 状态
     * @return
     */
    private void message(String title, String status, Map<String, String> msg) {
        Map<String, String> aliyun = new HashMap<>(16);
        aliyun.put("title", title);
        aliyun.put("status", status);
        msg.put("1", JsonUtil.getObjectToString(aliyun));
        msg.put("2", "2");
    }
}
